﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Media;

namespace VisualView
{
    public class GeometriesView : DrawingVisualView
    {
        public GeometriesView()
        {
            base.Visual = new DrawingVisual();
        }

        /// <summary>
        /// 数据源集合
        /// </summary>
        public ObservableCollection<GeometryDataSource> DataSource
        {
            get { return (ObservableCollection<GeometryDataSource>)GetValue(DataSourceProperty); }
            set { SetValue(DataSourceProperty, value); }
        }
        public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource", typeof(ObservableCollection<GeometryDataSource>), typeof(GeometriesView), new PropertyMetadata(DataSourceChanged));
        protected static void DataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is GeometriesView sv)
            {
                if (e.OldValue is ObservableCollection<GeometryDataSource> ov)
                {
                    ov.CollectionChanged -= sv.DataSource_CollectionChanged;
                    foreach (var ds in ov) if (sv.RegistedDataSource.Contains(ds)) { ds.PropertyChanged -= sv.DataSource_PropertyChanged; sv.RegistedDataSource.Remove(ds); }
                }
                if (e.NewValue is ObservableCollection<GeometryDataSource> nv)
                {
                    nv.CollectionChanged += sv.DataSource_CollectionChanged;
                    foreach (var ds in nv) if (!sv.RegistedDataSource.Contains(ds)) { ds.PropertyChanged += sv.DataSource_PropertyChanged; sv.RegistedDataSource.Add(ds); }
                }
                sv.Refresh();
            }
        }
        private void DataSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (e.NewItems != null) foreach (var item in e.NewItems) if (item is GeometryDataSource ds && !RegistedDataSource.Contains(ds)) { ds.PropertyChanged += DataSource_PropertyChanged; RegistedDataSource.Add(ds); }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    if (e.OldItems != null) foreach (var item in e.OldItems) if (item is GeometryDataSource ds && RegistedDataSource.Contains(ds)) { ds.PropertyChanged -= DataSource_PropertyChanged; RegistedDataSource.Remove(ds); }
                    break;
                case NotifyCollectionChangedAction.Replace:
                    if (e.OldItems != null) foreach (var item in e.OldItems) if (item is GeometryDataSource ds && RegistedDataSource.Contains(ds)) { ds.PropertyChanged -= DataSource_PropertyChanged; RegistedDataSource.Remove(ds); }
                    if (e.NewItems != null) foreach (var item in e.NewItems) if (item is GeometryDataSource ds && !RegistedDataSource.Contains(ds)) { ds.PropertyChanged += DataSource_PropertyChanged; RegistedDataSource.Add(ds); }
                    break;
                case NotifyCollectionChangedAction.Move:
                    break;
                case NotifyCollectionChangedAction.Reset:
                    if (RegistedDataSource.Count > 0)
                    {
                        foreach (var ds in RegistedDataSource) ds.PropertyChanged -= DataSource_PropertyChanged;
                        RegistedDataSource.Clear();
                    }
                    break;
                default:
                    break;
            }
        }
        List<GeometryDataSource> RegistedDataSource { get; } = new List<GeometryDataSource>();
        private void DataSource_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (nameof(GeometryDataSource.Geometry).Equals(e.PropertyName) || nameof(GeometryDataSource.FillBrush).Equals(e.PropertyName) || nameof(GeometryDataSource.StrokePen).Equals(e.PropertyName)) Refresh();
        }
        /// <summary>
        /// 刷新
        /// </summary>
        public virtual void Refresh()
        {
            using (var dc = Visual.RenderOpen())
            {
                if (DataSource != null && DataSource.Count > 0) foreach (var ds in DataSource) { dc.DrawGeometry(ds.FillBrush, ds.StrokePen, ds.Geometry); }
            }
        }
    }

    /// <summary>
    /// 矢量数据显示的数据源
    /// </summary>
    public class GeometryDataSource : BindableBase
    {
        private Brush fillBrush = Brushes.Transparent;
        /// <summary>
        /// 填充色
        /// </summary>
        public Brush FillBrush
        {
            get { return fillBrush; }
            set { SetProperty(ref fillBrush, value); }
        }

        private Pen strokePen = GeometryView.DefaultPen;
        /// <summary>
        /// 线条笔刷
        /// </summary>
        public Pen StrokePen
        {
            get { return strokePen; }
            set { SetProperty(ref strokePen, value); }
        }

        private Geometry geometry;
        /// <summary>
        /// 矢量数据
        /// </summary>
        public Geometry Geometry
        {
            get { return geometry; }
            set { SetProperty(ref geometry, value); }
        }

    }
}
